const express = require('express');
const morgan = require('morgan');
const expressWs = require('express-ws');
const bcrypt = require('bcrypt');
const ssh2 = require('ssh2');
const session = require('express-session');
const promClient = require('prom-client');

const app = express();

// 日志
// const fs = require('fs');
// const path = require('path');
// const accessLogStream = fs.createWriteStream(path.join(__dirname, 'access.log'), { flags: 'a' });
// app.use(morgan('combined', { stream: accessLogStream }));
app.use(morgan('combined'))

// 日志

// 指标
const counter = new promClient.Counter({
  name: 'http_requests_total',
  help: '请求总数',
  labelNames: ['method', 'path', 'status']
});

promClient.collectDefaultMetrics(); // 收集默认的node指标
// 将指标暴露出去
app.get('/metrics', async (req, res) => {
  res.set('Content-Type', promClient.register.contentType);
  res.end(await promClient.register.metrics());
});
app.use((req, res, next) => {
  // 每次请求，计数+1
  counter.inc({ method: req.method, path: req.path, status: res.statusCode });
  next()
})
// 指标


// 链路追踪
app.use((req, res, next) => {
  res.header('x-request-id', req.header('x-request-id'));
  res.header('x-b3-traceid', req.header('x-b3-traceid'));
  res.header('x-b3-spanid', req.header('x-b3-spanid'));
  res.header('x-b3-parentspanid', req.header('x-b3-parentspanid'));
  res.header('x-b3-sampled', req.header('x-b3-sampled'));
  res.header('x-b3-flags', req.header('x-b3-flags'));
  res.header('x-ot-span-context', req.header('x-ot-span-context'));
  next()
})
// 链路追踪


// 内存会话
const sessionStore = new session.MemoryStore();
// 设置会话密钥
app.use(session({
  secret: 'mysecretkey',
  store: sessionStore,
  resave: true,
  saveUninitialized: true
}));
// 内存会话

// 请求体解析
app.use(express.json()); // 用于解析application/json格式的请求
app.use(express.urlencoded({ extended: true })); // 用于解析application/x-www-form-urlencoded格式的请求
// 设置静态资源目录
app.use(express.static('public'));
app.use(express.static(__dirname));
// 请求体解析



// 路由
app.get('/', (req, res) => {
  res.sendFile(__dirname + '/public/login.html');
});

app.post('/login', (req, res) => {
  const { username, password } = req.body;

  // 假设我们有一个用户存储在数据库中
  const user = {
    id: 1,
    username: 'admin',
    password: '$2a$10$vIxeP.ZYcriF6mpAecVdD.oezfbzC/cyqhY1tTMfizd38p7API/UC'
  };

  if (username === user.username && bcrypt.compareSync(password, user.password)) {
    req.session.user = { id: user.id, username: user.username };
    res.redirect('/dashboard');
  } else {
    res.status(401).send('Invalid login credentials');
  }
});



// 认证中间件
const authenticateUser = (req, res, next) => {
  if (req.session && req.session.user) {
    next();
  } else {
    res.status(401).send('Unauthorized');
  }
};

app.get('/dashboard', authenticateUser, (req, res) => {
  res.sendFile(__dirname + '/public/dashboard.html');
});

// 将 WebSocket 功能添加到 Express 应用程序中
expressWs(app);
app.ws('/connect/:host', (ws, req) => {
  // console.log('websocket 已建立')

  // 根据用户权限检查是否允许连接主机
  const host = req.params.host;

  // 之后只需要host,token即可
  const username = req.query.username;
  const password = req.query.password;
  const port = req.query.port

  if (!req.session && !req.session.user) {
    res.status(401).send('Unauthorized');
  }
  // console.log(host, port, username, password)
  // 创建SSH连接
  const ssh = new ssh2.Client();
  ssh.connect({
    host,
    port,
    username,
    password
  });


  ssh.on('ready', () => {
    // 当SSH连接准备就绪时，启用shell模式
    ssh.shell((err, stream) => {
      if (err) {
        console.error(err)
        // 如果发生错误，则关闭SSH连接并关闭WebSocket连接
        ssh.end();
        ws.close();
        return;
      }
      var command = null
      // 前端发来的信息
      ws.on('message', (msg) => {
        // 发送WebSocketClient发来的消息到SSH服务器
        // console.log(`收到消息 ${msg}`)
        command = msg
        stream.write(`${msg}\r`);
      });

      // 当SSH服务器返回数据时，将其发送回WebSocket客户端
      stream.on('data', (data) => {
        // console.log(`给前端: ${data}`)
        if (command === data.toString().trim()) {
          command = ''
          ws.send('\r\n')
          return
        }
        ws.send(data.toString());
      });

      // 当WebSocket客户端关闭连接时，关闭SSH连接并关闭WebSocket连接
      ws.on('close', () => {
        stream.end('exit\r');
        ssh.end();
      });
    });
  });


});
// 路由




// 异常
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});

// 启动服务器
app.listen(3000, () => {
  console.log('Server listening on port 3000');
});

